#define _CRT_SECURE_NO_WARNINGS



#include"myhash.hpp"
namespace myunordered_map
{
   
	template<class T>
	struct round
	{
		size_t operator()(const T& key)
		{
			return (size_t)key;
		}
	};

	template<>
	struct round<string>
	{
		size_t operator()(const string& key)
		{
			size_t hash = 0;
			for (auto e : key)
			{
				hash *= 31;
				hash += e;
			}

			return hash;
		}
	};


	template<class K,class V,class Hash = round<K>,class Pred = equal_to<K>>
	class unordered_map
	{
		struct KeyOfV
		{
			const K& operator()(const pair<const K, V>& obj)
			{
				return obj.first;
			}
		};
	public:
		typedef typename myhash::hash<K, pair<const K, V>, Hash, Pred, KeyOfV>::Iterator iterator;
		typedef typename myhash::hash<K, pair<const K, V>, Hash, Pred, KeyOfV>::ConstIterator const_iterator;

		bool empty() const
		{
			return hashtable.empty();
		}
		size_t size()const
		{
			return hashtable.size();
		}
		iterator begin()
		{
			return hashtable.begin();
		}
		iterator end()
		{
			return hashtable.end();
		}
		const_iterator begin()const
		{
			return hashtable.begin();
		}
		const_iterator end()const
		{
			return hashtable.end();
		}
		iterator find(const K& key)
		{
			return hashtable.find(key);
		}
		const_iterator find(const K& key) const
		{
			return hashtable.find(key);
		}
		size_t count(const K& key) const
		{
			if (find(key) != end())
				return 1;
			else
				return 0;
		}
		pair<iterator, bool> insert(const pair<K,V>& data)
		{
			return hashtable.insert(data);
		}
		bool erase(const K&key)
		{
			return hashtable.erase(key);
		}
		void swap(unordered_map& obj)
		{
			hashtable.swap(obj.hashtable);
		}
		void reserve(size_t n)
		{
			hashtable.reserve(n);
		}
		V& operator[] (const K& key)
		{
			pair<iterator, bool>tmp = insert(make_pair(key, V()));
			iterator it = tmp.first;
			return it->second;
		}
	private:
		myhash::hash<K, pair<const K,V>, Hash, Pred, KeyOfV> hashtable;
	};
}